package br.com.news.service;

import java.io.IOException;
import java.io.Reader;
import java.util.List;

import android.content.Context;
import br.com.news.activity.json.Http;
import br.com.news.activity.json.Http.ConnectionType;
import br.com.news.activity.json.ParseJson;
import br.com.news.dao.NoticiaDao;
import br.com.news.dao.interfaces.INoticiaDao;
import br.com.news.exception.ConnectionException;
import br.com.news.exception.DataException;
import br.com.news.exception.ServiceException;
import br.com.news.modal.CategoriaBean;
import br.com.news.modal.NoticiaBean;
import br.com.news.service.interfaces.ICategoriaService;
import br.com.news.service.interfaces.INoticiaService;
import br.com.news.util.Constantes;
import br.com.news.util.FileUtil;

import com.google.gson.reflect.TypeToken;

public class NoticiaService implements INoticiaService {

	private INoticiaDao noticiaDao;
	private ICategoriaService categoriaService;

	public NoticiaService(Context context) {
		noticiaDao = new NoticiaDao(context);
		categoriaService = new CategoriaService(context);
	}

	@Override
	public long salvar(NoticiaBean noticiaBean) throws ServiceException {
		try {
			return noticiaDao.salvar(noticiaBean);
		} catch (DataException e) {
			throw new ServiceException(String.format("<NoticiaService> Falha ao salvar registro %d", noticiaBean.getId()), e);
		}
	}

	@Override
	public void atualizar(NoticiaBean noticiaBean) throws ServiceException {
		try {
			noticiaDao.atualizar(noticiaBean);
		} catch (DataException e) {
			throw new ServiceException(String.format("<NoticiaService> Falha ao atualizar registro %d", noticiaBean.getId()), e);
		}
	}

	@Override
	public long inserir(NoticiaBean noticiaBean) throws ServiceException {
		try {
			return noticiaDao.inserir(noticiaBean);
		} catch (DataException e) {
			throw new ServiceException(String.format("<NoticiaService> Falha ao inserir registro %d", noticiaBean.getId()), e);
		}
	}

	@Override
	public int deletar(long idNoticia) throws ServiceException {
		try {
			return noticiaDao.deletar(new NoticiaBean(idNoticia));
		} catch (DataException e) {
			throw new ServiceException(String.format("<NoticiaService> Falha ao deletar registro ", idNoticia), e);
		}
	}

	@Override
	public NoticiaBean findId(long idNoticia) throws ServiceException {
		try {
			NoticiaBean noticiaBean = noticiaDao.findId(new NoticiaBean(idNoticia));
			noticiaBean.setCategoria(categoriaService.findId(noticiaBean.getCategoria().getId()));
			return noticiaBean;
		} catch (DataException e) {
			throw new ServiceException(String.format("<NoticiaService> Falha ao buscar registro pelo id %d", idNoticia), e);
		}
	}

	@Override
	public List<NoticiaBean> findAll() throws ServiceException {
		try {
			List<NoticiaBean> noticiaBeans = noticiaDao.findAll(new NoticiaBean());

			for (NoticiaBean bean : noticiaBeans) {
				bean.setCategoria(categoriaService.findId(bean.getCategoria().getId()));
			}

			return noticiaBeans;
		} catch (DataException e) {
			throw new ServiceException(String.format("<NoticiaService> Falha ao buscar todos os registro"), e);
		}
	}

	@Override
	public List<NoticiaBean> findNoticiaByIdCategoria(long idCategoria) throws ServiceException {
		try {
			List<NoticiaBean> noticiaBeans = noticiaDao.findNoticiaByIdCategoria(idCategoria);
			/*CategoriaBean categoriaBean = categoriaService.findId(idCategoria);

			if (noticiaBeans != null) {
				for (NoticiaBean bean : noticiaBeans) {
					bean.setCategoria(categoriaBean);
				}
			}*/
			return noticiaBeans;

		} catch (DataException e) {
			throw new ServiceException(String.format("<NoticiaService> Falha ao buscar noticias pela categoria: %d", idCategoria), e);
		}
	}

	@Override
	public void fechar() {
		noticiaDao.fechar();
	}

	@Override
	public void deleteAllNews() throws ServiceException {
		try {
			noticiaDao.deletar(new NoticiaBean(), null, null);
		} catch (DataException e) {
			throw new ServiceException("<NoticiaService> Falha ao deletar todas as noticias!", e);
		}
	}
	
	@Override
	public String buscaTextoNoticia(long idNoticia) throws ServiceException{
		try {
			Reader reader = Http.connection(ConnectionType.GET, String.format(Constantes.URL_TEXTO_NOTICIA, idNoticia), null);
			try {
				return FileUtil.readString(reader);
			} catch (IOException e) {
				throw new ServiceException("<NoticiaService> Falha ao ler arquivo sincronizado", e);
			}
		} catch (ConnectionException e) {
			throw new ServiceException("<NoticiaService> Falha ao sincronizar as noticias anteriores com o servidor!", e);
		} 
	}
	
	@Override
	public void sincronizaUltimasNoticias(long idNoticia, long idCategoria) throws ServiceException{
		try {
			Reader reader = Http.connection(ConnectionType.GET, String.format(Constantes.URL_ULTIMAS_NOTICIAS, idNoticia, idCategoria), null);
			insertNoticiasSincronizadas((new ParseJson<NoticiaBean>()).parseObjectList(new TypeToken<List<NoticiaBean>>() {}.getType(), reader), idCategoria);
		} catch (ConnectionException e) {
			throw new ServiceException("<NoticiaService> Falha ao sincronizar as noticias anteriores com o servidor!", e);
		} 
	}

	@Override
	public void sincronizaNoticiasAnteriores(long idNoticia, long idCategoria) throws ServiceException{
		try {
			Reader reader = Http.connection(ConnectionType.GET, String.format(Constantes.URL_NOTICIAS_ANTERIORES, 15, idNoticia, idCategoria), null);
			insertNoticiasSincronizadas((new ParseJson<NoticiaBean>()).parseObjectList(new TypeToken<List<NoticiaBean>>() {}.getType(), reader), idCategoria);
		} catch (ConnectionException e) {
			throw new ServiceException("<NoticiaService> Falha ao sincronizar as noticias anteriores com o servidor!", e);
		} 
	}
	
	private void insertNoticiasSincronizadas(List<NoticiaBean> noticiaBeans, long idCategoria) throws ServiceException{
		try {
			for (NoticiaBean noticiaBean : noticiaBeans) {
				if (noticiaBean.getFonte() != null) {
					noticiaBean.setDescricaoFonte(noticiaBean.getFonte().getDescricao());
				}
				noticiaBean.setCategoria(new CategoriaBean(idCategoria));
				noticiaDao.inserir(noticiaBean);
			}
		} catch (DataException e) {
			throw new ServiceException("<NoticiaService> Falha ao salvar noticias sincronizadas!", e);
		}
	}

	@Override
	public NoticiaBean buscaUltimaNoticia(long idCategoria) throws ServiceException{
		try {
			return noticiaDao.buscaUltimaNoticia(idCategoria);
		} catch (DataException e) {
			throw new ServiceException("<NoticiaService> Falha ao buscar ultima noticia da categoria!", e);
		}
	}

}
